package edu.hit.pact.pgse.crawler.handler;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoConnector;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;

import edu.hit.pact.pgse.bean.Task;
import edu.hit.pact.pgse.bean.TaskPiece;
import edu.hit.pact.pgse.client.ClientManager;
import edu.hit.pact.pgse.communication.message.TaskPiecePushMessage;
import edu.hit.pact.pgse.communication.message.TaskPushMessage;
import edu.hit.pact.pgse.crawler.CrawlerManager;
import edu.hit.pact.pgse.crawler.util.SleepThread;

public class CrawlerMasterHandler extends IoHandlerAdapter{
	private Log logger;
	private CrawlerManager crawlerManager;
	
	public CrawlerMasterHandler(CrawlerManager crawlerManager){
		this.logger = LogFactory.getLog(CrawlerMasterHandler.class);
		this.crawlerManager = crawlerManager;
	}
	/*
	 * (non-Javadoc)
	 * @see org.apache.mina.core.service.IoHandlerAdapter#sessionOpened(org.apache.mina.core.session.IoSession)
	 */
	public void sessionOpened(IoSession session) {
		logger.info("session open");
		crawlerManager.setMasterSession(session);
	}//end for
	
    public void sessionCreated(IoSession session) {
    	// set idle time to MAX_IDLE_TIME seconds
    }
    
    @Override
	public void sessionClosed(IoSession session) throws Exception {
		logger.error("session is closed");
		session.close(true);
        logger.error("after closing, the address is "+ session.getRemoteAddress());
        reConnect(session);
	}
    
    /*
     * (non-Javadoc)
     * @see org.apache.mina.core.service.IoHandlerAdapter#messageReceived(org.apache.mina.core.session.IoSession, java.lang.Object)
     */
    @Override
    public void messageReceived(IoSession session, Object message) {
    	logger.error("message receive");
    	if (!(message instanceof TaskPiecePushMessage)){
    		logger.error("type error");
    	}
    	logger.info("to get piece");
    	TaskPiece piece = ((TaskPiecePushMessage)message).getPiece();
    	logger.info(piece);
    	crawlerManager.processTaskPiecePush(piece);
    	
    }
	
    /*
     * (non-Javadoc)
     * @see org.apache.mina.core.service.IoHandlerAdapter#sessionIdle(org.apache.mina.core.session.IoSession, org.apache.mina.core.session.IdleStatus)
     */
	public void sessionIdle(IoSession session, IdleStatus status) {
		logger.info("is idle, do nothing");
	
	}
    
	/*
	 * (non-Javadoc)
	 * @see org.apache.mina.core.service.IoHandlerAdapter#exceptionCaught(org.apache.mina.core.session.IoSession, java.lang.Throwable)
	 */
    @Override
    public void exceptionCaught(IoSession session, Throwable cause) {
        logger.error("Unexpected exception.", cause);
        cause.printStackTrace();
        // Close connection when unexpected exception is caught.
        session.close(true);
    }
    
    public boolean reConnect(IoSession session){
    	IoConnector connector = (IoConnector) session.getService();
    	for(int i=0; i<3; i++){
            try {
                ConnectFuture future = connector.connect(session.getRemoteAddress());
                future.join();
                crawlerManager.setMasterSession(future.getSession());
                return true;
            } catch (RuntimeException e) {
                logger.error("Failed to connect.");
                SleepThread.sleep(5000);
            }
        }
    	return false;
    }
}
